package cloud.lysky.java.on.concurrent.thread;

import java.util.Random;
import java.util.concurrent.*;

/**
 * @author luoly
 * @describe
 * @date 2023/2/28 9:25
 **/
/* 演示Future Callable FutureTask的使用 */
public class FutureTaskDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        /**
         *  FutureTask类实现了RunnableFuture接口，RunnableFuture继承了Runnable接口和Future接口，
         *  而FutureTask实现了RunnableFuture接口。所以它既可以作为Runnable被线程执行，
         *  又可以作为Future得到Callable的返回值。
         *  因此我们通过一个线程运行Callable，但是Thread不支持构造方法中传递Callable的实例，
         *  所以我们需要通过FutureTask把一个Callable包装成Runnable，
         *  然后再通过这个FutureTask拿到Callable运行后的返回值。
         */
        //创建callable
        MyCallable myCallable = new MyCallable();
        //使用FutureTask包装
        FutureTask<Integer> futureTask = new FutureTask<>(myCallable);
        //放入线程执行
        Thread myThread = new Thread(futureTask);
        myThread.start();

        Random random = new Random();
        Thread.sleep(1);
        //一定条件下获取结果或者中断线程
        if (random.nextInt(100) > 50) {
            System.out.println("Get callable result=" + futureTask.get());
        } else {
            System.out.println("cancel...");
            // 中断线程
            futureTask.cancel(true);
        }
    }
}
class MyCallable implements Callable<Integer> {
    private int sum = 0;
    @Override
    public Integer call() throws Exception {
        System.out.println("callable thread start calculate.");
        Thread.sleep(1000);
        for (int i = 0; i < 5000; i++) {
            //判断线程是否被中断
            if (Thread.currentThread().isInterrupted()){
                System.out.println("callable thread is end.");
                return sum;
            }
            sum += i;
            System.out.println("The value now is：" + sum);
        }
        return sum;
    }
}
